home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1997 August / Macworld (1997-08).dmg / Shareware World / Info / For Developers / InstallerMaker™ 4.0 Installer / Customizing InstallerMaker / Sample Code / Utilities / IMPackages256.c next >
Text File  |  1995-08-03  |  10KB  |  342 lines

  1.  
  2. /******************************************************************************
  3. **
  4. **  Project Name:    InstallerMaker 3.0 Demo Code
  5. **     File Name:    IMPackages256.c
  6. **
  7. **   Description:    These are useful routines for manipulating the IM 3.0 package
  8. **                    bit strings.
  9. **                     
  10. **        Packages field
  11. **        ==============
  12. **        
  13. **        The interpretation of packages for the code rsrcs is:
  14. **        
  15. **        IM 2.0: packages should be interpreted as a 16 bit field. 
  16. **            Bit 0 is the lowest bit.
  17. **        
  18. **        IM 3.0: packages should be interpreted as a 128 bit field. 
  19. **            packages[0] contains bits 0-31 where 0 is the lowest bit. 
  20. **            packages[1] contains bits 32-63 where 32 is the lowest bit.
  21. **             Similarly for packages[2] and packages[3].
  22. **        
  23. **        packages is a bit mask where bit 0 set means std pkg, bit 1
  24. **            set means pkg A, bit 2 means B, etc.  For compatibility, a
  25. **            value of zero is synonymous with all ones.
  26. **            
  27. **        The packages field typically specifies the currently selected
  28. **            pkgs unless otherwise noted.
  29. **        
  30. **
  31. **   Copyright© 1994-1995 Aladdin Systems, inc.
  32. **
  33. *******************************************************************************
  34. **                      L E G A L   N I C E T I E S
  35. *******************************************************************************
  36.  
  37.     This source code is (c) 1995 Aladdin Systems, Inc.  You are free to use it 
  38.     in connection with your own products and distribute it in either source code 
  39.     or object code form.  However, this source code and accompanying written 
  40.     materials (including instructions for use) are provided "as is" without 
  41.     warranty of any kind.  Further, Aladdin Systems does not warrant, or make 
  42.     representations regarding the use, or the results of the use, of the source 
  43.     code or written materials in terms of correctness, accuracy, reliability, 
  44.     currentness, or otherwise.  No oral or written information or advice given 
  45.     by Aladdin Systems or its employees shall create a warranty, and you may not 
  46.     rely on such information or advice.
  47.     
  48.     Neither Aladdin Systems nor anyone else who has been involved with the 
  49.     creation, production, or delivery of the source code shall be liable for 
  50.     any direct, indirect, consequential, or incidental damages (including damages 
  51.     for loss of business profits, business interruption, loss of business 
  52.     information, and the like) arising out of the use or the inability to use the 
  53.     source code even if Aladdin Systems has been advised of the possibility of 
  54.     such damages.  Because some states do not allow the exclusion or limitation 
  55.     of liability for consequential or incidental damages or the limitations of 
  56.     duration of implied warranty, the above limitations may not apply to you.
  57.  
  58. *******************************************************************************
  59. **                       A U T H O R   I D E N T I T Y
  60. *******************************************************************************
  61. **
  62. **    Initials    Name
  63. **    --------    -----------------------------------------------
  64. **    RMT            Robert Thorne
  65. **
  66. *******************************************************************************
  67. **                      R E V I S I O N   H I S T O R Y
  68. *******************************************************************************
  69. **
  70. **      Date        Time    Author    Description
  71. **    --------    -----    ------    ---------------------------------------------
  72. **    1/2/95                RMT        Pulled from test code for new file
  73. **
  74. ******************************************************************************/
  75.  
  76. #include "IMPackages256.h"
  77.  
  78.  
  79. // Utility routines to do fast string manipulations
  80. static    void    TransToUpperCase ( StringPtr str ) ;
  81. static  char *CopyAsCStr ( StringPtr pStr, char *cStr ) ;
  82.  
  83. //Defines for quick translation of characters
  84. #define NumToLetter( num )  ((num) + 'A' - 1 )
  85. #define kLowerToUpper    ('a' - 'A' )
  86. #define kMaxCodeLen 4
  87.  
  88. // Converts a string in place to uppercase
  89. void  TransToUpperCase ( StringPtr str )
  90. {
  91.     register StringPtr sPtr = str, lim = str + str[0] + 1;
  92.     char    c ;
  93.     
  94.     if ( sPtr )
  95.     {
  96.         sPtr++ ; // pass on the length bit
  97.         
  98.         while ( sPtr < lim )
  99.         {
  100.             c = *sPtr ;
  101.             if ( 'a' <= c && c <= 'z' )
  102.                 *sPtr -= kLowerToUpper ; // 'a' > 'A' in ASCII
  103.                 
  104.             sPtr++ ;
  105.         }
  106.     }
  107. }
  108.     
  109.     
  110. // Copies a Pascal string from pStr to the C string cStr, converting it
  111. // in the same operation.
  112. static char *CopyAsCStr ( StringPtr pStr, char *cStr ) 
  113. {
  114.     short    len = pStr [0] , index ;
  115.     unsigned char    *cPtr =  (unsigned char *) cStr ; // We don't want the compiler
  116.                                                        // mangling 8-bit codes
  117.     
  118.     *cPtr = 0 ;    // In case we have a null string
  119.     
  120.     if (len)
  121.     {
  122.         for (index = 1; index <= len ; index++, cPtr++ ) 
  123.             *cPtr =  pStr [index] ;
  124.         *cPtr = 0 ;
  125.     }
  126.             
  127.     return cStr ;
  128. }
  129.  
  130. //**** PUBLIC INTERFACE STARTS HERE...
  131.  
  132. //*** GetPackageNumber ***
  133.         
  134. // Valid formats are "Std" for "Standard Package", "A"..."Z", and "AA".."DW".
  135. // Pass these as Pascal strings.  This routine is case-insensitive.
  136.  
  137. short    GetPackageNumber ( StringPtr pkgStr )
  138. {
  139.     short     len = pkgStr[0] ;
  140.     short    rslt = -1 ; // for "Not a package"
  141.     char    c ;
  142.     
  143.     TransToUpperCase (pkgStr) ;
  144.     
  145.     switch (len)
  146.     {
  147.         case    1: // A-Z
  148.             c = pkgStr[1] ;
  149.             if ( 'A'<= c && c <= 'Z' )
  150.                 rslt = c - 'A' + 1 ;
  151.                 
  152.             break ;
  153.             
  154.         case    2: // AA - DV
  155.             c = pkgStr[1] ;
  156.             if ( 'A' <= c && c <= 'D' )
  157.             {
  158.                 rslt = (c - 'A' + 1) * 26 ;
  159.                 c = pkgStr [2] ;
  160.                 if ( 'A'<= c && c <= 'Z' )
  161.                     rslt += c - 'A' + 1 ;
  162.                 else
  163.                     rslt = -1 ;
  164.             }
  165.             break ;
  166.             
  167.         case    3: // The standard package; "\pSTD" is the only valid combo
  168.             if ( pkgStr[1] == 'S' &&
  169.                  pkgStr[2] == 'T' &&
  170.                  pkgStr[3] == 'D' ) rslt = 0 ;
  171.                  
  172.             break ;
  173.     } 
  174.     
  175.     return rslt < 128 ? rslt : -1 ; // Make sure the number is actually valid
  176. }
  177.  
  178.  
  179. //*** GetPkgLetters ***
  180.  
  181. // Passes back a string that represents that package number.  Currently, the
  182. // largest string this passes back is 4 bytes (for "Std"), but allocate a little
  183. // more for safety.
  184.  
  185. char    *GetPkgLetters ( short pkgCode, char *smallStr )
  186. {
  187.     // Currently, longest string is 3 letters.  May change.
  188.     short    lowPart, highPart ;
  189.     char    *cPtr = smallStr ;
  190.     
  191.     if ( pkgCode > 0 && pkgCode < 128  ) // a letter code
  192.     {
  193.         highPart = pkgCode/26 ;
  194.         lowPart = pkgCode - highPart*26 ;
  195.         
  196.         if ( highPart > 0 )
  197.         {
  198.             *cPtr = NumToLetter( highPart ) ;
  199.             cPtr++ ;
  200.         }
  201.         
  202.         *cPtr = NumToLetter( lowPart ) ;
  203.         
  204.         cPtr++ ;
  205.         
  206.         *cPtr = 0 ; // Final null to close string.
  207.         
  208.     }
  209.     else if ( pkgCode == 0 ) // Std package
  210.     {
  211.         *cPtr = 'S' ; cPtr++ ;
  212.         *cPtr = 't' ; cPtr++ ;
  213.         *cPtr = 'd' ; cPtr++ ;
  214.         *cPtr = 0 ; 
  215.     }
  216.     else // Bad value
  217.     {
  218.         *cPtr = '\?' ; cPtr++ ;
  219.         *cPtr = 0 ; 
  220.     }
  221.  
  222.     return smallStr ;
  223.     
  224. }
  225.  
  226.  
  227. //*** GetPackageBit ***
  228.  
  229. // Checks if bit # bitNo is set in the packages array.  This passes back
  230. // 0 if not set, 1 if set, and -1 for an illegal bitNo.
  231.  
  232. short    GetPackageBit ( unsigned long *packages, short bitNo )
  233. {
  234.     // return 0 or 1 for good; -1 for a bad number
  235.     short rslt , group, offset ;
  236.     if ( bitNo < 128 && bitNo >= 0 ) // valid
  237.     {
  238.         group = bitNo / 32 ; // which long?
  239.         offset = bitNo - group * 32 ; // which bit within the group?
  240.         rslt = ((1L << offset ) & packages [group]) != 0 ;
  241.     }
  242.     else
  243.         rslt = -1 ;
  244.         
  245.     return rslt ;
  246. }
  247.  
  248.  
  249. //*** SetPackageBit ***
  250.  
  251. // Turns on or turns off bit bitNo.  
  252.  
  253. void    SetPackageBit ( unsigned long *packages, short bitNo, Boolean turnOn )
  254. {
  255.     // We set the bit we want if it's in the valid range; otherwise, we do nothing
  256.     short group, offset ;
  257.     if ( bitNo < 128 && bitNo >= 0 ) // valid
  258.     {
  259.         group = bitNo / 32 ; // which long?
  260.         offset = bitNo - group * 32 ; // which bit within the group?
  261.         
  262.         if ( turnOn )
  263.             packages [group] |= (1L << offset ) ;
  264.         else
  265.             packages [group] &= ~(1L << offset ) ;
  266.     }
  267. }    
  268.  
  269. //*** ConstructPkgString ***
  270.  
  271. // Returns a comma-delimited string listing the package bits set.  Note that
  272. // this list can get rather long: an average of 3 chars per set bit means you
  273. // can require up to 360 bytes if all bits are set.
  274.  
  275. // Note:  safer if I took a length argument and stopped adding bits.
  276.  
  277. char    *ConstructPkgString ( unsigned long *packages, char *store, short storeLen ) 
  278. {
  279.     // Be careful to have enough store for this routine, since on average
  280.     // each bit set will require 3 bytes.  512 is probably safe.
  281.     
  282.     short    i = 0 , j = 0 , group = 0, offset = 0 ;
  283.     char     oneCode [10] ;
  284.     char    lastTerminator = 0 ; // a comma, an elipsis, or nothing
  285.     char    *endOfStr = store , *cPtr ;
  286.     char    *rightMargin = store + storeLen - 1 ; // This points to the last possible byte
  287.     long    thisLong ;
  288.     Boolean    outtaSpace = true ;
  289.     
  290.     // Terminate our storage if safe to do so
  291.     if ( store && storeLen > 0 )
  292.     {
  293.         store [0] = 0 ;
  294.         
  295.         // Confirm we have enough space to do anything
  296.         outtaSpace = ( storeLen < kMaxCodeLen + 1) ;
  297.     }
  298.     
  299.     while ( !outtaSpace &&  i < 4 ) // step down each of the longs in the array
  300.     {
  301.         if (thisLong = packages[i]) // assignment intended
  302.         {
  303.             j = 0 ; // initialize this run through the loop
  304.             
  305.             while ( !outtaSpace && j < 32 )
  306.             {
  307.                 // Test each of the bits and print if need be
  308.                 if ((1L << j) & thisLong)
  309.                 {
  310.                     (void) GetPkgLetters ( j + i*32, oneCode ) ; // get the letters
  311.                     cPtr = oneCode ;
  312.                     while ( *cPtr ) // let's walk to the end of the string and copy
  313.                         *endOfStr++ = *cPtr++ ;
  314.                     
  315.                     // Do we have room for another?
  316.                     if ( endOfStr + kMaxCodeLen > rightMargin )
  317.                     {
  318.                         outtaSpace = true ;
  319.                         *endOfStr++ = lastTerminator = '…' ; // copy over an elipsis
  320.                     }
  321.                     *endOfStr++ = lastTerminator = ',' ; // copy over a comma
  322.                 }
  323.                 
  324.                 j++ ; // Next bit in this group
  325.             }
  326.         }
  327.             
  328.         i++ ; // Next 32 bits
  329.     }
  330.     
  331.     // Remove a trailing comma if it's there...
  332.     if ( lastTerminator == ',' )
  333.         endOfStr-- ;
  334.     
  335.     if ( store )
  336.         *endOfStr = 0 ; // Terminate with a null 
  337.     
  338.     return store ;
  339. }
  340.  
  341.                     
  342.